package com.simpleim.starter.server;

import com.simpleim.codec.SimpleProtobufDecoder;
import com.simpleim.codec.SimpleProtobufEncoder;
import com.simpleim.starter.handler.LoginRequestHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class ChatServer {

    private static final Logger LOG = LoggerFactory.getLogger(ChatServer.class);

    @Value("${server.port}")
    private String port;

    @Autowired
    private LoginRequestHandler loginRequestHandler;

    public void run() {
        ServerBootstrap bootstrap = new ServerBootstrap();

        // 父线程
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);

        // 子线程
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            bootstrap.group(bossGroup, workerGroup);

            bootstrap.channel(NioServerSocketChannel.class);
            bootstrap.option(ChannelOption.SO_KEEPALIVE, true);

            // 设置worker线程处理器
            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    // protobuf消息的编解码器
                    ch.pipeline().addLast(new SimpleProtobufDecoder());
                    ch.pipeline().addLast(new SimpleProtobufEncoder());
                    // 登录处理器
                    ch.pipeline().addLast("login", loginRequestHandler);
                }
            });

            bootstrap.localAddress(Integer.parseInt(port));

            ChannelFuture channelFuture = bootstrap.bind().sync();
            LOG.info("服务器在端口{}启动成功", port);

            Channel channel = channelFuture.channel();
            channel.closeFuture().sync();
            LOG.info("服务器关闭");
        } catch (Exception e) {
            LOG.error("服务器启动异常", e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
